#include "spline.cpp"
#include "jsonprocess.cpp"
#include "tool.hpp"
#include "funlib.h"

using namespace std;

void problemA()
{
    // 读取 JSON 文件
    json jsonArray = readJsonFile("jsonfile/problemA.json");
    constexpr int dim = 1, order = 3;
    const string filename[6] = {"Af0.txt", "Af1.txt", "Af2.txt", "Af3.txt", "Af4.txt", "Af5.txt"};
    vector<int> Ns{6, 11, 21, 41, 81};
    vector<double> num(5);
    vector<double> error(5);

    cout << "problemA: " << endl;
    outputFile(f1, filename[0], -1, 1);
    int i = 0;
    for (const auto &jsonData : jsonArray)
    {
        // 获取矩阵数据
        auto knots_curve = getFieldData<vector<vector<double>>>(jsonData, "curve");
        BoundConditionType bctp = getFieldData<BoundConditionType>(jsonData, "bctp");
        auto bc = getFieldData<vector<vector<double>>>(jsonData, "bc");
        Spline<dim, order, PiecewiseP> t1;
        t1.fitCurve(knots_curve, bctp, bc);
        outputFile<dim, order, PiecewiseP>(t1, filename[i + 1], 0.01);
        // 计算误差和收敛阶
        vector<double> evec(Ns[i] - 1);
        for (int j = 0; j < Ns[i] - 1; ++j)
        {
            double x = (knots_curve[0][j + 1] + knots_curve[0][j]) / 2;
            evec[j] = evaluate(t1, x) - f1(x);
        }
        error[i] = MaxNorm(evec);
        num[i] = Ns[i] - 1.0;
        cout << "num of subinterval: " << num[i] << "  error: " << error[i] << endl;
        ++i;
    }
    double cvod = ConvergenceOrder(num, error);
    cout << "Convergence Order: " << cvod << endl;
    cout << endl;
}

void problemBCD()
{
    // 读取 JSON 文件
    json jsonArray = readJsonFile("jsonfile/problemBCD.json");
    constexpr int dim = 1, order1 = 3, order2 = 2;
    const string filename[3] = {"Cf0.txt", "Cf1.txt", "Cf2.txt"};
    outputFile(f2, filename[0], -5, 5);
    int i = 0;
    // 定理3.57的样条插值,并输出
    json jsonData = jsonArray[i];
    auto knots_curve = getFieldData<vector<vector<double>>>(jsonData, "curve");
    BoundConditionType bctp = getFieldData<BoundConditionType>(jsonData, "bctp");
    auto bc = getFieldData<vector<vector<double>>>(jsonData, "bc");
    Spline<dim, order1, CardinalB> t1;
    t1.fitCurve(knots_curve, bctp, bc);
    outputFile<dim, order1, CardinalB>(t1, filename[i + 1], 0.01);
    ++i;
    // 定理3.58的样条插值,并输出
    jsonData = jsonArray[i];
    knots_curve = getFieldData<vector<vector<double>>>(jsonData, "curve");
    bctp = getFieldData<BoundConditionType>(jsonData, "bctp");
    bc = getFieldData<vector<vector<double>>>(jsonData, "bc");
    Spline<dim, order2, CardinalB> t2;
    t2.fitCurve(knots_curve, bctp, bc);
    outputFile<dim, order2, CardinalB>(t2, filename[i + 1], 0.01);
    ++i;

    cout << "problemD: " << endl;
    vector<double> error(7);
    vector<double> vec{-3.5, -3, -0.5, 0, 0.5, 3, 3.5};
    cout << std::setw(12) << "error1"
         << " " << std::setw(12) << "error2" << endl;
    for (int j = 0; j < 7; j++)
    {
        double x = vec[j];
        cout << std::setw(12) << fabs(evaluate<dim, order1, CardinalB>(t1, x) - f2(x)) << " "
             << std::setw(12) << fabs(evaluate<dim, order2, CardinalB>(t2, x) - f2(x)) << endl;
    }
    cout << endl;
}

void problemE()
{
    // 读取 JSON 文件
    json jsonArray = readJsonFile("jsonfile/problemE.json");
    constexpr int dim = 2, order = 3;
    const string filename[4] = {"Ef0.txt", "Ef1.txt", "Ef2.txt", "Ef3.txt"};

    outputFile(f_xt, f_yt, filename[0], 0, 2 * M_PI, 0.002 * M_PI);
    int i = 0;
    for (const auto &jsonData : jsonArray)
    {
        // 获取矩阵数据
        auto knots_curve = getFieldData<vector<vector<double>>>(jsonData, "curve");
        BoundConditionType bctp = getFieldData<BoundConditionType>(jsonData, "bctp");
        Spline<dim, order, B> t1;
        t1.fitCurve(knots_curve, bctp);
        outputFile<dim, order, B>(t1, filename[i + 1], 0.002 * M_PI);
        ++i;
    }
}

int main()
{
    problemA();
    problemBCD();
    problemE();
    return 0;
}